"""
信息检索智能体

基于LangGraph ReAct模式，检索债券、公告和新闻信息。
"""

from typing import Dict, Any, List, Optional
from langchain_core.tools import Tool
import pandas as pd

from agents import BondAnalysisAgent, LLMConfig
from tools.bond_data_provider import bond_data_provider


class InformationRetrievalAgent(BondAnalysisAgent):
    """信息检索智能体"""
    
    def __init__(self, llm_config: Optional[LLMConfig] = None):
        super().__init__(
            name="information_retrieval",
            description="检索债券、公告和新闻信息",
            llm_config=llm_config
        )
        
        self.analysis_dimensions = ["search", "retrieval"]
    
    def get_tools(self) -> List[Tool]:
        """获取信息检索所需的工具"""
        
        async def get_bond_info(bond_code: str) -> str:
            """获取指定债券代码的详细信息"""
            try:
                # 获取债券基本信息 (返回Dict)
                bond_info = await bond_data_provider.get_bond_basic_info(bond_code)
                
                if not bond_info:
                    return f"未找到债券代码为 {bond_code} 的信息"
                
                result = f"=== 债券信息 - {bond_code} ===\n\n"
                result += f"【基本信息】\n"
                result += f"债券代码: {bond_info.get('债券代码', 'N/A')}\n"
                result += f"债券简称: {bond_info.get('债券简称', 'N/A')}\n"
                result += f"正股代码: {bond_info.get('正股代码', 'N/A')}\n"
                result += f"正股名称: {bond_info.get('正股名称', 'N/A')}\n"
                result += f"信用评级: {bond_info.get('信用评级', 'N/A')}\n"
                
                result += f"\n【价格信息】\n"
                result += f"债券现价: {bond_info.get('债现价', 'N/A')}元\n"
                result += f"正股价: {bond_info.get('正股价', 'N/A')}元\n"
                result += f"转股价: {bond_info.get('转股价', 'N/A')}元\n"
                result += f"转股价值: {bond_info.get('转股价值', 'N/A')}元\n"
                result += f"转股溢价率: {bond_info.get('转股溢价率', 'N/A')}%\n"
                
                result += f"\n【估值指标】\n"
                result += f"纯债溢价率: {bond_info.get('纯债溢价率', 'N/A')}%\n"
                result += f"纯债价值: {bond_info.get('纯债价值', 'N/A')}元\n"
                
                result += f"\n【债券条款】\n"
                result += f"发行规模: {bond_info.get('发行规模', 'N/A')}亿元\n"
                result += f"剩余规模: {bond_info.get('剩余规模', 'N/A')}亿元\n"
                result += f"转股起始日: {bond_info.get('转股起始日', bond_info.get('开始转股日', 'N/A'))}\n"
                result += f"到期日: {bond_info.get('到期日', 'N/A')}\n"
                
                if bond_info.get('强赎触发价'):
                    result += f"\n【强赎信息】\n"
                    result += f"强赎触发价: {bond_info.get('强赎触发价', 'N/A')}元\n"
                    result += f"强赎状态: {bond_info.get('强赎状态', 'N/A')}\n"
                
                return result
            except Exception as e:
                return f"获取债券{bond_code}信息失败: {str(e)}"
        
        async def search_bonds_by_name(keyword: str) -> str:
            """根据关键词搜索债券"""
            try:
                results = await bond_data_provider.search_bonds_by_name(keyword)
                
                if not results:
                    return f"未找到包含'{keyword}'的债券"
                
                result = f"=== 债券搜索结果（关键词: {keyword}）===\n\n"
                result += f"找到 {len(results)} 个匹配结果：\n\n"
                
                for idx, bond in enumerate(results, 1):
                    result += f"{idx}. 【{bond['债券代码']} - {bond['债券简称']}】\n"
                    result += f"   发行人: {bond.get('正股名称', 'N/A')}\n"
                    result += f"   正股代码: {bond.get('正股代码', 'N/A')}\n"
                    result += f"   最新价: {bond.get('最新价', 'N/A')}元\n"
                    result += "\n"
                
                if len(results) > 10:
                    result += f"（显示前10个结果，共{len(results)}个）\n"
                
                return result
            except Exception as e:
                return f"搜索债券失败: {str(e)}"
        
        async def search_bonds_by_rating(rating: str) -> str:
            """根据评级搜索债券"""
            try:
                # 获取所有债券详情
                all_bonds = await bond_data_provider.get_bond_detail()
                
                if all_bonds.empty:
                    return "未获取到债券数据"
                
                # 筛选指定评级的债券
                if '债券评级' in all_bonds.columns:
                    filtered = all_bonds[all_bonds['债券评级'] == rating]
                else:
                    return "债券数据中缺少评级信息"
                
                if filtered.empty:
                    return f"未找到评级为 {rating} 的债券"
                
                result = f"=== 评级搜索结果（评级: {rating}）===\n\n"
                result += f"找到 {len(filtered)} 个 {rating} 评级的债券：\n\n"
                
                # 按到期收益率排序
                if '到期收益率' in filtered.columns:
                    filtered = filtered.sort_values('到期收益率', ascending=False)
                
                # 显示前20个结果
                for idx, (_, row) in enumerate(filtered.head(20).iterrows(), 1):
                    result += f"{idx}. 【{row.get('债券代码', 'N/A')} - {row.get('债券简称', 'N/A')}】\n"
                    result += f"   最新价: {row.get('最新价', 'N/A')}元\n"
                    result += f"   到期收益率: {row.get('到期收益率', 'N/A')}%\n"
                    result += f"   转股溢价率: {row.get('转股溢价率', 'N/A')}%\n"
                    result += "\n"
                
                if len(filtered) > 20:
                    result += f"（显示前20个结果，共{len(filtered)}个）\n"
                
                return result
            except Exception as e:
                return f"按评级搜索债券失败: {str(e)}"
        
        async def search_bonds_by_price_range(min_price: float, max_price: float) -> str:
            """根据价格区间搜索债券"""
            try:
                # 获取所有债券实时数据
                all_bonds = await bond_data_provider.get_bond_realtime_data()
                
                if all_bonds.empty:
                    return "未获取到债券数据"
                
                # 筛选价格区间
                if '最新价' in all_bonds.columns:
                    filtered = all_bonds[
                        (all_bonds['最新价'] >= min_price) & 
                        (all_bonds['最新价'] <= max_price)
                    ]
                else:
                    return "债券数据中缺少价格信息"
                
                if filtered.empty:
                    return f"未找到价格在 {min_price}-{max_price} 元之间的债券"
                
                result = f"=== 价格区间搜索结果（{min_price}-{max_price}元）===\n\n"
                result += f"找到 {len(filtered)} 个符合条件的债券：\n\n"
                
                # 按价格排序
                filtered = filtered.sort_values('最新价', ascending=True)
                
                # 显示前20个结果
                for idx, (_, row) in enumerate(filtered.head(20).iterrows(), 1):
                    result += f"{idx}. 【{row.get('债券代码', 'N/A')} - {row.get('债券简称', 'N/A')}】\n"
                    result += f"   最新价: {row.get('最新价', 'N/A')}元\n"
                    result += f"   涨跌幅: {row.get('涨跌幅', 'N/A')}%\n"
                    result += f"   成交额: {row.get('成交额', 'N/A')}万元\n"
                    result += "\n"
                
                if len(filtered) > 20:
                    result += f"（显示前20个结果，共{len(filtered)}个）\n"
                
                return result
            except Exception as e:
                return f"按价格区间搜索债券失败: {str(e)}"
        
        async def get_high_yield_bonds(min_ytm: float = 3.0) -> str:
            """获取高收益率债券（默认收益率>=3%）"""
            try:
                # 使用bond_zh_cov获取更全面的数据（985条 vs 30条）
                all_bonds = await bond_data_provider.get_bond_realtime_data()
                
                if all_bonds.empty:
                    return "未获取到债券数据"
                
                # 注意：bond_zh_cov可能不包含"到期收益率"字段
                # 作为替代，使用"转股溢价率"的负值来筛选潜在高收益债券
                # 原理：低溢价率通常意味着更高的转股价值和潜在收益
                if '转股溢价率' in all_bonds.columns:
                    # 转换为数值类型
                    all_bonds['转股溢价率'] = pd.to_numeric(all_bonds['转股溢价率'], errors='coerce')
                    # 筛选低溢价率债券（作为高收益的代理指标）
                    # 溢价率 < 20% 通常表示较好的投资价值
                    filtered = all_bonds[all_bonds['转股溢价率'] < 20]
                    
                    if filtered.empty:
                        return f"未找到转股溢价率低于20%的债券（高收益潜力债券）"
                    
                    result = f"=== 高收益潜力债券（转股溢价率<20%）===\n\n"
                    result += f"找到 {len(filtered)} 个高收益潜力债券：\n\n"
                    result += "⚠️ 说明：由于数据源限制，使用\"低转股溢价率\"(<20%)作为高收益的代理指标\n"
                    result += "原理：低溢价率通常意味着更高的转股价值和潜在收益\n\n"
                    
                    # 按溢价率排序（从低到高）
                    filtered = filtered.sort_values('转股溢价率', ascending=True)
                    
                    # 显示前15个结果
                    for idx, (_, row) in enumerate(filtered.head(15).iterrows(), 1):
                        result += f"{idx}. 【{row.get('债券代码', 'N/A')} - {row.get('债券简称', 'N/A')}】\n"
                        result += f"   转股溢价率: {row.get('转股溢价率', 'N/A')}%\n"
                        result += f"   债现价: {row.get('债现价', 'N/A')}元\n"
                        result += f"   转股价值: {row.get('转股价值', 'N/A')}元\n"
                        result += f"   信用评级: {row.get('信用评级', 'N/A')}\n"
                        result += "\n"
                    
                    if len(filtered) > 15:
                        result += f"（显示前15个结果，共{len(filtered)}个）\n"
                    
                    result += "\n✓ 投资建议：关注债券评级和发行人信用，低溢价率债券适合看好正股的投资者\n"
                    
                    return result
                else:
                    return "债券数据中缺少转股溢价率信息"
                
            except Exception as e:
                return f"获取高收益潜力债券失败: {str(e)}"
        
        async def get_low_premium_bonds(max_premium: float = 20.0) -> str:
            """获取低溢价债券（默认转股溢价率<=20%）"""
            try:
                # 获取所有债券详情
                all_bonds = await bond_data_provider.get_bond_detail()
                
                if all_bonds.empty:
                    return "未获取到债券数据"
                
                # 筛选低溢价债券
                if '转股溢价率' in all_bonds.columns:
                    # 转换为数值类型并过滤
                    all_bonds['转股溢价率'] = pd.to_numeric(all_bonds['转股溢价率'], errors='coerce')
                    filtered = all_bonds[all_bonds['转股溢价率'] <= max_premium]
                else:
                    return "债券数据中缺少溢价率信息"
                
                if filtered.empty:
                    return f"未找到转股溢价率 <= {max_premium}% 的债券"
                
                result = f"=== 低溢价债券（转股溢价率<={max_premium}%）===\n\n"
                result += f"找到 {len(filtered)} 个低溢价债券：\n\n"
                
                # 按溢价率排序
                filtered = filtered.sort_values('转股溢价率', ascending=True)
                
                # 显示前15个结果
                for idx, (_, row) in enumerate(filtered.head(15).iterrows(), 1):
                    result += f"{idx}. 【{row.get('债券代码', 'N/A')} - {row.get('债券简称', 'N/A')}】\n"
                    result += f"   转股溢价率: {row.get('转股溢价率', 'N/A')}%\n"
                    result += f"   最新价: {row.get('最新价', 'N/A')}元\n"
                    result += f"   转股价值: {row.get('转股价值', 'N/A')}元\n"
                    result += f"   债券评级: {row.get('债券评级', 'N/A')}\n"
                    result += "\n"
                
                if len(filtered) > 15:
                    result += f"（显示前15个结果，共{len(filtered)}个）\n"
                
                result += "\n✓ 提示：低溢价债券转股价值较高，适合看好正股的投资者\n"
                
                return result
            except Exception as e:
                return f"获取低溢价债券失败: {str(e)}"
        
        async def get_double_low_bonds(max_double_low: float = 130.0) -> str:
            """获取双低债券（默认双低值<=130）"""
            try:
                # 使用bond_zh_cov获取更全面的数据（985条 vs 30条）
                all_bonds = await bond_data_provider.get_bond_realtime_data()
                
                if all_bonds.empty:
                    return "未获取到债券数据"
                
                # 计算双低值（债现价 + 转股溢价率）
                if '债现价' in all_bonds.columns and '转股溢价率' in all_bonds.columns:
                    all_bonds['债现价'] = pd.to_numeric(all_bonds['债现价'], errors='coerce')
                    all_bonds['转股溢价率'] = pd.to_numeric(all_bonds['转股溢价率'], errors='coerce')
                    # 双低值 = 债券价格 + 转股溢价率
                    all_bonds['双低值'] = all_bonds['债现价'] + all_bonds['转股溢价率']
                    
                    # 过滤掉无效数据
                    filtered = all_bonds[
                        (all_bonds['双低值'].notna()) &
                        (all_bonds['双低值'] <= max_double_low)
                    ]
                else:
                    return "债券数据中缺少必要信息（债现价或转股溢价率）"
                
                if filtered.empty:
                    return f"未找到双低值 <= {max_double_low} 的债券"
                
                result = f"=== 双低债券（双低值<={max_double_low}）===\n\n"
                result += f"找到 {len(filtered)} 个双低债券：\n\n"
                result += "💡 双低值 = 债现价 + 转股溢价率，数值越低表示性价比越高\n\n"
                
                # 按双低值排序
                filtered = filtered.sort_values('双低值', ascending=True)
                
                # 显示前15个结果
                for idx, (_, row) in enumerate(filtered.head(15).iterrows(), 1):
                    result += f"{idx}. 【{row.get('债券代码', 'N/A')} - {row.get('债券简称', 'N/A')}】\n"
                    result += f"   双低值: {row.get('双低值', 0):.2f}\n"
                    result += f"   债现价: {row.get('债现价', 'N/A')}元\n"
                    result += f"   转股溢价率: {row.get('转股溢价率', 'N/A')}%\n"
                    result += f"   转股价值: {row.get('转股价值', 'N/A')}元\n"
                    result += f"   信用评级: {row.get('信用评级', 'N/A')}\n"
                    result += "\n"
                
                if len(filtered) > 15:
                    result += f"（显示前15个结果，共{len(filtered)}个）\n"
                
                result += "\n✓ 投资建议：双低债券兼具价格优势和转股价值，性价比较高，适合稳健投资\n"
                
                return result
            except Exception as e:
                return f"获取双低债券失败: {str(e)}"
        
        # 创建工具列表
        tools = [
            Tool(
                name="get_bond_info",
                description="获取指定债券代码的详细信息。参数为6位债券代码（如'123222'）",
                func=lambda bond_code: None,
                coroutine=get_bond_info,
            ),
            Tool(
                name="search_bonds_by_name",
                description="根据债券名称关键词搜索债券，支持模糊匹配。例如：'银行'、'转债'等",
                func=lambda keyword: None,
                coroutine=search_bonds_by_name,
            ),
            Tool(
                name="search_bonds_by_rating",
                description="根据评级搜索债券。评级参数如：'AAA'、'AA+'、'AA'、'AA-'等",
                func=lambda rating: None,
                coroutine=search_bonds_by_rating,
            ),
            Tool(
                name="search_bonds_by_price_range",
                description="根据价格区间搜索债券。需要两个参数：最低价格和最高价格（单位：元）",
                func=lambda min_price, max_price: None,
                coroutine=search_bonds_by_price_range,
            ),
            Tool(
                name="get_high_yield_bonds",
                description="获取高收益潜力债券列表（使用低转股溢价率作为代理指标）。参数为最低收益率阈值（默认3.0，实际使用溢价率<20%筛选）",
                func=lambda min_ytm=3.0: None,
                coroutine=get_high_yield_bonds,
            ),
            Tool(
                name="get_low_premium_bonds",
                description="获取低转股溢价率债券列表。参数为最大溢价率（默认20%）",
                func=lambda max_premium=20.0: None,
                coroutine=get_low_premium_bonds,
            ),
            Tool(
                name="get_double_low_bonds",
                description="获取双低债券列表（债现价+转股溢价率）。参数为最大双低值（默认130），双低值越低表示性价比越高",
                func=lambda max_double_low=130.0: None,
                coroutine=get_double_low_bonds,
            ),
        ]
        
        return tools
    
    def get_system_prompt(self) -> str:
        """获取系统提示词"""
        return """你是一个专业的债券信息检索专家，负责帮助用户查找和筛选债券。

你的检索能力：
1. get_bond_info - 获取指定债券代码的详细信息
2. search_bonds_by_name - 根据名称关键词搜索
3. search_bonds_by_rating - 根据评级搜索
4. search_bonds_by_price_range - 根据价格区间搜索
5. get_high_yield_bonds - 获取高收益潜力债券（使用低转股溢价率<20%作为代理指标）
6. get_low_premium_bonds - 获取低溢价债券（转股溢价率<=20%）
7. get_double_low_bonds - 获取双低债券（债现价+转股溢价率<=130）

使用建议：
- 如果用户提供了具体的债券代码（6位数字），使用 get_bond_info 获取详细信息
- 如果用户提供了具体条件（评级、价格、收益率等），优先使用对应的专门工具
- 如果用户只提供关键词，使用 search_bonds_by_name
- 如果用户寻求"性价比高"或"双低"债券，使用 get_double_low_bonds（兼具价格和转股价值优势）
- 如果用户关注"转股价值"或"低溢价"，使用 get_low_premium_bonds
- 如果用户关注"高收益"或"潜力"，使用 get_high_yield_bonds（实际筛选低溢价率债券）

重要说明：
- get_high_yield_bonds 由于数据源限制，使用"低转股溢价率"作为高收益的代理指标
- 低溢价率债券通常意味着更高的转股价值和潜在收益，适合看好正股的投资者
- 双低债券兼具价格优势和转股价值，是稳健投资的优选标的

请根据用户需求选择合适的检索工具，展示检索结果，并提供简要说明。
"""


# 全局实例
information_retrieval_agent = InformationRetrievalAgent()